package com.fary.context.annotation;

import com.fary.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import com.fary.beans.factory.config.BeanDefinitionCustomizer;
import com.fary.beans.factory.config.BeanDefinitionHolder;
import com.fary.beans.factory.support.AutowireCandidateQualifier;
import com.fary.beans.factory.support.BeanDefinitionReaderUtils;
import com.fary.beans.factory.support.BeanDefinitionRegistry;
import com.fary.beans.factory.support.BeanNameGenerator;
import com.fary.core.env.Environment;
import com.fary.core.env.EnvironmentCapable;
import com.fary.core.env.StandardEnvironment;
import com.fary.util.Assert;

import java.lang.annotation.Annotation;
import java.util.function.Supplier;

public class AnnotatedBeanDefinitionReader {

    // 这个reader对象主要的工作就是注册BeanDefinition，那么将BeanDefinition注册到哪里去呢？所以它内部就保存了一个BeanDefinition的注册表。
    // 对应的就是我们代码中的AnnotationConfigApplicationContext
    private final BeanDefinitionRegistry registry;

    // 见名知意，Bean名称的生成器，生成BeanName
    private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();

    // 解析@Scope注解
    private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();

    // 解析@Conditional注解
    private ConditionEvaluator conditionEvaluator;

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
    }

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry instanceof EnvironmentCapable) {
            return ((EnvironmentCapable) registry).getEnvironment();
        }
        return new StandardEnvironment();
    }

    public void register(Class<?>... annotatedClasses) {
        for (Class<?> annotatedClass : annotatedClasses) {
            registerBean(annotatedClass);
        }
    }

    public void registerBean(Class<?> annotatedClass) {
        doRegisterBean(annotatedClass, null, null, null);
    }

    <T> void doRegisterBean(Class<T> annotatedClass, Supplier<T> instanceSupplier, String name, Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

        // 将Bean配置类信息转成容器中AnnotatedGenericBeanDefinition数据结构,
        // AnnotatedGenericBeanDefinition继承自BeanDefinition作用是定义一个bean的数据结构，下面的
        // getMetadata可以获取到该bean上的注解信息
        // 通过reader对象注册的BeanDefinition都是AnnotatedGenericBeanDefinition
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        //@Conditional装配条件判断是否需要跳过注册
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }
        //设置回调
        abd.setInstanceSupplier(instanceSupplier);
        //解析bean作用域(单例或者原型)，如果有@Scope注解，则解析@Scope，没有则默认为singleton
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        //作用域写回BeanDefinition数据结构, abd中缺损的情况下为空，将默认值singleton重新赋值到abd
        abd.setScope(scopeMetadata.getScopeName());
        //生成bean配置类beanName
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
        //通用注解解析到abd结构中，主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        // @Qualifier特殊限定符处理，
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    // 如果配置@Primary注解，则设置当前Bean为自动装配autowire时首选bean
                    abd.setPrimary(true);
                } else if (Lazy.class == qualifier) {
                    //设置当前bean为延迟加载
                    abd.setLazyInit(true);
                } else {
                    //其他注解，则添加到abd结构中
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        // 自定义bean注册，通常用在applicationContext创建后，手动向容器中以lambda表达式的方式注册bean,
        // 比如：applicationContext.registerBean(UserService.class, () -> new UserService());
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            // 自定义bean添加到BeanDefinition
            customizer.customize(abd);
        }

        //根据beanName和bean定义信息封装一个beanhold,heanhold其实就是一个 beanname和BeanDefinition的映射
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        //创建代理对象
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        // BeanDefinitionReaderUtils.registerBeanDefinition
        // 内部通过DefaultListableBeanFactory.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        // 按名称将bean定义信息注册到容器中，
        // 实际上DefaultListableBeanFactory内部维护一个Map<String, BeanDefinition>类型变量
        // beanDefinitionMap，用于保存注bean定义信息（beanname 和 beandefine映射）
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}